﻿using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using StackExchange.Redis;
using System.Text.Json;

namespace Redis_ClientInfor
{
    /// <summary>
    /// Redis 客户端类，用于操作 Redis 数据库的连接和数据操作
    /// </summary>
    public class RedisClient
    {


        private static readonly object Locker = new object();

        private ConnectionMultiplexer redisMultiplexer;

        private readonly IConfiguration configuration;

        IDatabase db = null;

        private static RedisClient _redisClient = null;

        /// <summary>
        /// 获取 RedisClient 的单例实例
        /// </summary>
        public static RedisClient redisClient
        {
            get
            {
                if (_redisClient == null)
                {
                    lock (Locker)
                    {
                        if (_redisClient == null)
                        {
                            _redisClient = new RedisClient();

                        }
                    }
                }
                return _redisClient;
            }
        }

        /// <summary>
        /// 初始化 Redis 连接
        /// </summary>
        public void InitConnect()
        {
            try
            {
                var GetConfig = "10.31.59.21,DefaultDatabase=0";
                redisMultiplexer = ConnectionMultiplexer.Connect(GetConfig);
                db = redisMultiplexer.GetDatabase();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                redisMultiplexer = null;
                db = null;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public RedisClient()
        {

        }

        /// <summary>
        /// 保存单个 key value 到 Redis 中
        /// </summary>
        /// <param name="key">键名</param>
        /// <param name="value">保存的值</param>
        /// <param name="expiry">过期时间</param>
        /// <returns>设置是否成功</returns>
        public bool SetStringKey(string key, string value, TimeSpan? expiry = default(TimeSpan?))
        {
            return db.StringSet(key, value, expiry);
        }

        /// <summary>
        /// 获取单个key的值
        /// </summary>
        /// <param name="key">键名</param>
        /// <returns>字符串值</returns>
        public RedisValue GetStringKey(string key)
        {
            return db.StringGet(key);
        }


        /// <summary>
        /// 获取一个key的对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">键名</param>
        /// <returns>对象值</returns>
        public T GetStringKey<T>(string key)
        {
            if (db == null)
            {
                return default;
            }
            var value = db.StringGet(key);
            if (value.IsNullOrEmpty)
            {
                return default;
            }
            return JsonConvert.DeserializeObject<T>(value);
        }

        /// <summary>
        /// 设置指定 key 的对象值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">键名</param>
        /// <param name="obj">对象值</param>
        /// <param name="expiry">过期时间</param>
        /// <returns>设置是否成功</returns>
        public bool SetStringKey<T>(string key, T obj, TimeSpan? expiry = default(TimeSpan?))
        {
            if (db == null)
            {
                return false;
            }
            string json = JsonConvert.SerializeObject(obj);
            return db.StringSet(key, json, expiry);
        }


        /// <summary>
        /// 设置指定 Hset 的对象值(异步)
        /// </summary>
        /// <typeparam name="T">返回的对象</typeparam>
        /// <param name="myKey">第一个键</param>
        /// <param name="Key">数据的键</param>
        /// <param name="obj">数据的值</param>
        /// <param name="expiry">时间设置 默认为 null </param>
        /// <returns>bool</returns>
        public async Task<bool> HsetInforAsync<T>(string? myKey,string? Key, T obj, TimeSpan? expiry = default(TimeSpan?))
        {
            if (db == null)
            {
                return false;
            }
            string json = JsonConvert.SerializeObject(obj);
            var res = await db.HashSetAsync(myKey, Key,json);
            if(expiry != null)
            {
                await db.KeyExpireAsync(Key, expiry);
            }
            return res;
        }

        /// <summary>
        /// 获取 Hget 的值
        /// </summary>
        /// <typeparam name="T">对象</typeparam>
        /// <param name="myKey">第一个键</param>
        /// <param name="Key">数据的键</param>
        /// <returns>T</returns>
        public async Task<T> HgetInforAsync<T>(string? myKey, string? Key)
        {
            if (db == null)
            {
                return default;
            }
            var value = await db.HashGetAsync(myKey, Key);
            if (value.IsNullOrEmpty)
            {
                return default;
            }
            return JsonConvert.DeserializeObject<T>(value);

        }
    }
}
